package ch.bfh.ti.pixelator.preferences;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import ch.bfh.ti.barcode.colorQrCode.ColorQrCodeGenerator;
import ch.bfh.ti.pixelator.R;
import ch.bfh.ti.pixelator.camera.CameraManager;

public class MainPreferenceFragment extends PreferenceFragment implements
		OnSharedPreferenceChangeListener {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// Load the preferences from an XML resource
		addPreferencesFromResource(R.xml.preferences);

		refreshResolutionList();

		// Set frame sizes
		ListPreference frameSize = (ListPreference) getPreferenceManager()
				.findPreference("frameSizePref");
		int[] frameSizes = ColorQrCodeGenerator
				.getOptimalBlockSizeInformation();
		String[] frameSizesString = Arrays.toString(frameSizes).split(
				"[\\[\\]]")[1].split(", ");
		frameSize.setEntries(frameSizesString);
		frameSize.setEntryValues(frameSizesString);
		if (!Arrays.asList(frameSizesString).contains(frameSize.getValue()))
			frameSize.setValueIndex(0);
	}

	/**
	 * Set camera resolutions. Cache them in to properties so we don't have to
	 * get the camera object every time the properties are refreshed.
	 */
	private void refreshResolutionList() {
		SharedPreferences pref = PreferenceManager
				.getDefaultSharedPreferences(getActivity());

		Set<String> cameraResolutions = pref.getStringSet(
				"savedCameraResolutions", new LinkedHashSet<String>());

		// To check if the saved values are for the right camera
		boolean cameraPref = pref.getBoolean("cameraPref", false);
		boolean savedCameraPref = pref.getBoolean(
				"savedCameraResolutionCamera", false);

		if (cameraResolutions.isEmpty() || cameraPref != savedCameraPref) {

			CameraManager manager = new CameraManager(getActivity());
			Camera camera = manager.OpenSelectedCamera();

			if (camera == null)
				return;

			List<Size> supportedPreviewSizes = camera.getParameters()
					.getSupportedPreviewSizes();
			camera.release();

			Set<String> entries = new LinkedHashSet<String>();
			Set<String> entryValues = new LinkedHashSet<String>();
			for (Size entry : supportedPreviewSizes) {
				if (!entryValues.contains(String.valueOf(entry.height))
						&& (float) entry.width / (float) entry.height <= 1.5) {
					entries.add(String.valueOf(entry.height) + "x"
							+ String.valueOf(entry.height));
					entryValues.add(String.valueOf(entry.height));
				}
			}

			SharedPreferences.Editor editor = pref.edit();
			editor.putBoolean("savedCameraResolutionCamera", cameraPref);
			editor.putStringSet("savedCameraResolutions", entries);
			editor.putStringSet("savedCameraResolutionValues", entryValues);
			editor.commit();
		}

		cameraResolutions = pref.getStringSet("savedCameraResolutions",
				new LinkedHashSet<String>());
		Set<String> cameraResolutionValues = pref.getStringSet(
				"savedCameraResolutionValues", new LinkedHashSet<String>());

		String[] sortedCameraResolutins = cameraResolutions
				.toArray(new String[cameraResolutions.size()]);
		Arrays.sort(sortedCameraResolutins);
		String[] sortedCameraResolutionValues = cameraResolutionValues
				.toArray(new String[cameraResolutionValues.size()]);
		Arrays.sort(sortedCameraResolutionValues);
				
		ListPreference cameraResolution = (ListPreference) getPreferenceManager()
				.findPreference("cameraResolution");

		cameraResolution.setEntries(sortedCameraResolutins);
		cameraResolution.setEntryValues(sortedCameraResolutionValues);

		if (!cameraResolutionValues.contains(cameraResolution.getValue()))
			cameraResolution.setValueIndex(0);
	}

	@Override
	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
			String key) {
		Preference preference = findPreference(key);

		// This is probably a bug in the android framework. The list has to be
		// refreshed manually.
		if (key.equals("cameraResolution")) {
			preference.setSummary(String.format(
					"The preview is being recorded with a resolution of %s pixels.",
					((ListPreference) preference).getEntry()));
		} else if (key.equals("frameSizePref")) {
			preference.setSummary(String.format(
					"A single RGB-QR-Code can store %s bytes.",
					((ListPreference) preference).getEntry()));
		} else if (key.equals("cameraPref")) {
			refreshResolutionList();
		}
	}

	@Override
	public void onResume() {
		super.onResume();
		getPreferenceManager().getSharedPreferences()
				.registerOnSharedPreferenceChangeListener(this);
	}

	@Override
	public void onPause() {
		getPreferenceManager().getSharedPreferences()
				.unregisterOnSharedPreferenceChangeListener(this);
		super.onPause();
	}
}
